#include "interrupt.h"
#include "sbi.h"
#include "timer.h"
#include "tinyprintf.h"

void interrupt_disable(void)
{
    w_sie(0);
    w_sip(0);
}

void interrupt_enable(void)
{
    w_sstatus(r_sstatus() | SSTATUS_SIE);
}

void enable_timer_interrupt(void)
{
  w_sie(r_sie() | SIE_STIE);
}

void enable_software_interrupt(void)
{
    w_sie(r_sie() | SIE_SSIE);
}

void enable_external_interrupt(void)
{
    w_sie(r_sie() | SIE_SEIE);
}

uintptr_t handle_trap(uintptr_t scause, uintptr_t stval, uintptr_t sepc, uintptr_t sp)
{
    tfp_printf("handle_trap %08lx:%08lx:%08lx:%08lx\n", scause, stval, sepc, sp);
    uint64 curr = get_cycle();
    switch (scause) {
        case SupervisorExternal:
            tfp_printf("Got IPI in %ld cycle\n", curr);
            break;
        case SupervisorTimer:
            tfp_printf("Got timer interrupt in %ld cycle\n", curr);
            break;
    }
    return 0;
}

void trap_handler(struct ctx *ctx) {
    uint64 curr = get_cycle();
    if ((ctx->scause & 0x8000000000000000) != 0)
    {
        switch (ctx->scause) {
            case SupervisorSoft:
                tfp_printf("Got IPI in %ld cycle\n", curr);
                SBI_ECALL_0(SBI_SHUTDOWN);
                break;
            case SupervisorTimer:
                tfp_printf("Got timer interrupt in %ld cycle\n", curr);
                break;
            default:
                tfp_printf("other interrupts\n");
        }
        w_sip(0);
    } else {
        switch (ctx->scause) {
            default:
                tfp_printf("other exceptions\n");
        }
    }
    return;
}
